﻿
using Dapper;
using HBase;
using MongoDB.Bson;
using MongoDB.Driver;
using Net.http;
using System;
using System.Data;
namespace hCommand {
    [Serializable]
    public abstract class GkTransaction {
        public String name;
        public GkTransaction() {
            name = this.GetType().Name;
        }

        private IDbConnection connection;
        protected virtual IDbConnection getConnection() {
            if( connection == null ) {
                connection = DBUtils.newWMSConn(BaseConfig.prefixal);
            }
            return connection;
        }
        /// <>
        ///抽象类执行方法
        /// </summary>
        /// <param name="errorMsg">错误消息返回</param>
        /// <returns></returns>
        public TransRes doWork() {
            IDbConnection connection = getConnection();
            if (connection.State == ConnectionState.Closed) {
                connection.Open();  
            }
            IDbTransaction transaction = null;
            try {
                 transaction = connection.BeginTransaction();
            }catch(Exception e) {
                connection.Close();
                LoggerCommon.error(InfoCode.error_transaction, "事务开启异常", e);
                connection.Open();
                return new TransRes("开启事务异常,请重试3次");
            }
           
            long time = DateTime.Now.Ticks / 10000;
            try {
                TransRes res = Execute(connection ,transaction);
                if( res.s ) {
                    transaction.Commit();
                } else {
                    transaction.Rollback();
                    log(res.msg ,time);
                }
                return res;
            } catch( Exception ex ) {
              

                transaction.Rollback();

                LoggerCommon.error(InfoCode.error_transaction,ex.Message ,ex);
                log(ex.Message + ex.StackTrace ,time);
                return new TransRes(ex.Message);
            } finally {
                if( connection.State == ConnectionState.Open ) {
                    //connection.Close();
                }
            }
        }
        void log(String error ,long begin) {
            try {
                if( LoggerCommon.loggerMongon ) {
                    long time = DateTime.Now.Ticks / 10000 - begin;
                    IMongoCollection<BsonDocument> collection = ConnectionCache.getMongoCollection<GkTransaction>();
                    BsonDocument document = new BsonDocument();
                    document.Add("info" , JsonUtil.toView(this));
                    document.Add("time" ,DateTime.Now);
                    document.Add("error" ,error);
                    document.Add("ip" ,NetConfig.MeIp);
                    document.Add("use" ,( int ) time);
                    document.Add("_id" ,HUtil.to64());
                    collection.InsertOne(document);
                }
            } catch { }
        }
        //protected abstract bool Execute(IDbConnection connection, IDbTransaction transaction);
        /// <summary>
        /// 重写基础类方便，在库存计算入出库wcs任务生成过程中各种业务逻辑判断错误消息返回上层调用方法 by leo.yang 20200723
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="transaction"></param>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        protected abstract TransRes Execute(IDbConnection connection ,IDbTransaction transaction);

        public T getById<T>(long id ,IDbConnection conn ,IDbTransaction transaction) where T : class {
            return conn.GetById<T>(id ,transaction);
        }
        public bool updateNotNull<T>(T t ,IDbConnection conn ,IDbTransaction transaction) where T : class {
            return conn.updateNotNull(t ,transaction);
        }
        public long insert<T>(T t ,IDbConnection conn ,IDbTransaction transaction) where T : class {
            return conn.Insert<T>(t ,transaction);
        }

        public static void exec(IDbConnection Conn ,IDbTransaction tr ,string sql ,object p) {
            Conn.Execute(sql ,p ,tr);
        }
    }
}
